namespace Terra.Core.Common.ErrorCodes.Registration;

using System.Reflection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Terra.Core.Common.ErrorCodes.Options;
using Terra.Core.Common.ErrorCodes.Providers;

/// <summary>
/// 错误码初始化器
/// </summary>
public class ErrorCodeInitializer : IHostedService
{
    private readonly IErrorCodeProvider _errorCodeProvider;
    private readonly ErrorCodeOptions _options;
    private readonly ILogger<ErrorCodeInitializer> _logger;

    public ErrorCodeInitializer(
        IErrorCodeProvider errorCodeProvider,
        IOptions<ErrorCodeOptions> options,
        ILogger<ErrorCodeInitializer> logger)
    {
        _errorCodeProvider = errorCodeProvider;
        _options = options.Value;
        _logger = logger;
    }

    /// <inheritdoc />
    public Task StartAsync(CancellationToken cancellationToken)
    {
        if (!_options.AutoRegister)
        {
            _logger.LogInformation("错误码自动注册已禁用");
            return Task.CompletedTask;
        }

        try
        {
            // 获取要扫描的程序集
            var assemblies = GetAssembliesToScan();

            // 注册错误码
            ErrorCodeRegistration.RegisterFromAssemblies(_errorCodeProvider, assemblies.ToArray());

            // 验证错误码
            if (_options.EnableValidation)
            {
                ErrorCodeRegistration.ValidateErrorCodes(_errorCodeProvider);
            }

            _logger.LogInformation(
                "错误码注册完成，共注册 {Count} 个错误码",
                _errorCodeProvider.GetAllErrorCodes().Count);
        }
        catch (Exception ex)
        {
            _logger.LogError(ex, "错误码注册失败");
            if (_options.ThrowOnDuplicate)
            {
                throw;
            }
        }

        return Task.CompletedTask;
    }

    /// <inheritdoc />
    public Task StopAsync(CancellationToken cancellationToken)
    {
        return Task.CompletedTask;
    }

    /// <summary>
    /// 获取要扫描的程序集
    /// </summary>
    private IEnumerable<Assembly> GetAssembliesToScan()
    {
        var assemblies = new HashSet<Assembly>();

        // 添加当前程序集
        assemblies.Add(typeof(ErrorCodeInitializer).Assembly);

        // 添加配置指定的程序集
        foreach (var assemblyName in _options.ScanAssemblies)
        {
            try
            {
                var assembly = Assembly.Load(assemblyName);
                assemblies.Add(assembly);
            }
            catch (Exception ex)
            {
                _logger.LogWarning(ex, "加载程序集 {AssemblyName} 失败", assemblyName);
            }
        }

        return assemblies;
    }
}